using Sandia.MVCFramework.Common;
using System;
using System.Collections.Generic;
using System.Text;
using Sandia.MVCFramework.Request;

namespace Sandia.MVCFramework.Request
{
    /// <summary>
    /// A generic that creates requests that takes two parameters
    /// </summary>
    /// <remarks>
    /// This generic simplifies the creation both of the request and the underlying parameter types.
    /// It uses the ObjectParameter to create those types.  So you simply have to specify the object
    /// types that get stored as parameters and (if desired) expose the accessors using semantically
    /// meaningful names.
    /// </remarks>
    /// <typeparam name="T">The first type to be stored as a parameter</typeparam>
    /// <typeparam name="R">The second type to be stored as a parameter</typeparam>
    [Serializable]
    public class TwoParameterRequest<T, R> : AbstractStandardRequest
    {
        /// <summary>
        /// The string used as the name for the first parameter.
        /// </summary>
        private string p1Name = "p1";

        /// <summary>
        /// The string used as the name for the second parameter.
        /// </summary>
        private string p2Name = "p2";

        /// <summary>
        /// Create a new request
        /// </summary>
        /// <param name="p1">The first object to be stored as a parameter</param>
        /// <param name="p2">the second object to be stored as a parameter</param>
        public TwoParameterRequest(T p1, R p2)
        {
            // UNDONE JTM - This restriction is no longer necessary.
            //if (typeof(T).FullName.Equals(typeof(R).FullName))
            //{
            //    // JTM 20080425 - Changed to use the new SendToLog utility.
            //    LoggingTools.SendToLog(
            //        "TwoParameterRequest objects do not support two objects of the same type.", 
            //        LoggingCategories.ERROR, 
            //        100);
            //    return;
            //}

            parameters[p1Name] = new ObjectParameter<T>(p1);
            parameters[p2Name] = new ObjectParameter<R>(p2);
        }

        /// <summary>
        /// Accessor for the first type
        /// </summary>
        /// <remarks>
        /// Expose publicly in a subclass using a semantically meaningful name.
        /// </remarks>
        protected T Param1
        {
            get { return (T)parameters[p1Name].Data; }
            set { parameters[p1Name] = new ObjectParameter<T>(value); }
        }

        /// <summary>
        /// Accessor for the second type
        /// </summary>
        /// <remarks>
        /// Expose publicly in a subclass using a semantically meaningful name.
        /// </remarks>
        protected R Param2
        {
            get { return (R)parameters[p2Name].Data; }
            set { parameters[p2Name] = new ObjectParameter<R>(value); }
        }

        /// <summary>
        /// Initialize both parameters to null
        /// </summary>
        protected override void initParameters()
        {
            parameters[p1Name] = null;
            parameters[p2Name] = null;
        }

        // UNDONE JTM - We aren't going to use this right now. Revisit when we want to make the service controller do routing instead of broadcasting.
        ///// <summary>
        ///// Returns the unique ID for all instances of this request type. This
        ///// is to route requests.
        ///// </summary>
        ///// <returns>The unique type ID.</returns>
        //protected override string initRequestTypeID()
        //{
        //    return typeof(TwoParameterRequest<T, R>).ToString();
        //}
    }
}
